package cn.harry.modular.system.service.impl;

import cn.harry.common.exception.ApiException;
import cn.harry.common.model.Option;
import cn.harry.modular.system.domain.SysDept;
import cn.harry.modular.system.enums.StatusEnums;
import cn.harry.modular.system.exception.enums.SysExceptionEnum;
import cn.harry.modular.system.mapper.SysDeptMapper;
import cn.harry.modular.system.service.SysDeptService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author harry
 * @公众号 Harry技术
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept>
        implements SysDeptService {

    @Override
    public List<SysDept> selectDeptList(SysDept sysDept) {
        List<SysDept> deptList = this.baseMapper.selectList(Wrappers.lambdaQuery(sysDept));

        // 获取所有部门ID
        Set<Long> ids = deptList.stream().map(SysDept::getId).collect(Collectors.toSet());
        // 获取父节点ID
        Set<Long> parentIds = deptList.stream().map(SysDept::getPid).collect(Collectors.toSet());
        // 获取根节点ID（递归的起点），即父节点ID中不包含在部门ID中的节点，注意这里不能拿顶级部门 O 作为根节点，因为部门筛选的时候 O 会被过滤掉
        List<Long> rootIds = CollectionUtil.subtractToList(parentIds, ids);

        // 递归生成部门树形列表
        return rootIds.stream()
                .flatMap(rootId -> recursionList(rootId, deptList).stream())
                .toList();
    }

    @Override
    public List<Option<Long>> listDeptOptions() {

        List<SysDept> deptList = this.list(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getStatus, StatusEnums.ENABLE.getKey())
                .select(SysDept::getId, SysDept::getPid, SysDept::getName)
                .orderByAsc(SysDept::getSort)
        );
        if (CollectionUtil.isEmpty(deptList)) {
            return Collections.EMPTY_LIST;
        }

        Set<Long> deptIds = deptList.stream()
                .map(SysDept::getId)
                .collect(Collectors.toSet());

        Set<Long> parentIds = deptList.stream()
                .map(SysDept::getPid)
                .collect(Collectors.toSet());

        List<Long> rootIds = CollectionUtil.subtractToList(parentIds, deptIds);

        // 递归生成部门树形列表
        return rootIds.stream()
                .flatMap(rootId -> recurDeptTreeOptions(rootId, deptList).stream())
                .toList();
    }

    @Override
    public boolean createDept(SysDept sysDept) {
        sysDept.setAncestors(getAncestors(sysDept.getPid()));
        return save(sysDept);
    }


    @Override
    public boolean updateDept(SysDept sysDept) {
        sysDept.setAncestors(getAncestors(sysDept.getPid()));
        return updateById(sysDept);
    }

    /**
     * 获取祖级列表
     *
     * @param pid
     * @return
     */
    private String getAncestors(Long pid) {
        // 查询父级菜单 ParentId 信息
        SysDept dept = this.baseMapper.selectById(pid);
        if (dept == null || StatusEnums.DISABLE.getKey().equals(dept.getStatus())) {
            throw new ApiException(SysExceptionEnum.DEPT_NOT_EXISTS);
        }
        return dept.getAncestors() + "," + pid;
    }

    /**
     * 递归生成部门表格层级列表
     *
     * @param parentId 父ID
     * @param deptList 部门列表
     * @return 部门表格层级列表
     */
    public static List<Option<Long>> recurDeptTreeOptions(long parentId, List<SysDept> deptList) {
        return CollectionUtil.emptyIfNull(deptList).stream()
                .filter(dept -> dept.getPid().equals(parentId))
                .map(dept -> {
                    Option<Long> option = new Option<>(dept.getId(), dept.getName());
                    List<Option<Long>> children = recurDeptTreeOptions(dept.getId(), deptList);
                    if (CollectionUtil.isNotEmpty(children)) {
                        option.setChildren(children);
                    }
                    return option;
                })
                .collect(Collectors.toList());
    }

    private List<SysDept> recursionList(Long parentId, List<SysDept> deptList) {
        return deptList.stream()
                .filter(dept -> dept.getPid().equals(parentId))
                .map(dept -> {
                    SysDept deptVO = BeanUtil.copyProperties(dept, SysDept.class);
                    List<SysDept> children = recursionList(dept.getId(), deptList);
                    deptVO.setChildren(children);
                    return deptVO;
                }).toList();
    }
}




